<?php

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

namespace EasyActionPHP\Core;

use EasyActionPHP\Controller as Controller;

/**
 * Classe principal da aplicação web.
 *
 * @author Flavio de Vasconcellos Correa
 * @since 2007/06/04
 * @package EasyActionPHP
 * @subpackage Core
 * @version $id$
 * @license http://www.gnu.org/copyleft/gpl.html
 */
class Application {

    /**
     * @staticvar Application Singleton da classe.
     */
    static private $instance;

    /**
     * @var Array[Mixed] Parâmetros globais da aplicação.
     */
    private $params;

    /**
     * Constructor.
     */
    function __construct() {
        $this->params = Array();
    }

    /**
     * Retorna o objeto Singleton da classe.
     *
     * @access public
     * @return Application
     */
    public static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new Application();
        }
        return self::$instance;
    }

    /**
     * Retorna a lista de parâmetros globais da aplicação.
     *
     * @access public
     * @return Array[Mixed]
     */
    public static function getParamList() {
        $local_instance = self::getInstance();
        return $local_instance->params;
    }

    /**
     * Adiciona aos parametros um valor associado a chave.
     *
     * @access public
     * @param String key
     * @param Mixed value
     * @return void
     */
    public static function addParam($key, $value) {
        $local_instance = self::getInstance();
        $local_instance->params[$key] = $value;
    }

    /**
     * Retorna o conteúdo registrado associado a chave.
     *
     * @access public
     * @param String key
     * @return Mixed Conteúdo armazenado.
     */
    public static function getParamByName($key) {
        $local_instance = self::getInstance();
        if (array_key_exists($key, $local_instance->params)) {
            return $local_instance->params[$key];
        } else {
            return null;
        }
    }

    private static function isLoaded() {
        $cache = Controller\HttpRequest::getSessionParameter('__APPLICATION_CACHE');
        if (!is_null($cache)) {
            self::$instance = $cache;
            return true;
        }
        return false;
    }

    /**
     * Registra na aplica;ccedil;&atilde;o um arquivo de configura;ccedil;&atilde;o. V&aacute;rios arquivos podem ser registrados.<br/>
     * Sempre o &Uacute;ltimo sobrep;&otildee as defini;ccedil;&atilde;es do arquivo anterior. Portanto, <b>CUIDADO e CAUTELA</b>!
     *
     * @access public
     * @param String cfgFileName
     * @return void
     */
    public static function registerConfiguration($cfgFileName) {
        try {
            if (!file_exists($cfgFileName)) {
                throw new \Exception('ERROR: ' . $cfgFileName . ' configuration file not exists.');
            }
            $configStream = simplexml_load_file($cfgFileName);
            if ($configStream) {
                if (!self::isLoaded()) {
                    foreach ($configStream->{'smarty-template'} as $smarty_template) {
                        self::addParam('SMARTY-TEMPLATE-DIR', (string) $smarty_template->{'template-dir'});
                        self::addParam('SMARTY-CACHE-DIR', (string) $smarty_template->{'cache-dir'});
                        self::addParam('SMARTY-COMPILE-DIR', (string) $smarty_template->{'compile-dir'});
                        $plugins_dir = Array();
                        foreach ($smarty_template->{'plugins-dir'} as $plugin_dir) {
                            $plugins_dir[] = (string) $plugin_dir;
                        }
                        self::addParam('SMARTY-PLUGINS-DIR', $plugins_dir);
                    }

                    foreach ($configStream->{'database-resource'} as $database_resource) {
                        foreach ($database_resource->param as $param) {
                            $attributes = $param->attributes();
                            self::addParam((string) $attributes->name, (string) $attributes->value);
                        }
                    }

                    self::addParam('__LOCALE', 'en');
                    foreach ($configStream->{'locale-def'} as $locale_def) {
                        self::addParam('__LOCALE', (string) $locale_def);
                    }

                    setlocale(LC_ALL, self::getParamByName('__LOCALE'));

                    self::addParam('__ACTION_PARAM', 'do');
                    foreach ($configStream->{'action-param'} as $action_param) {
                        self::addParam('__ACTION_PARAM', (string) $action_param);
                    }
                    Controller\HttpRequest::setSessionParameter('__APPLICATION_CACHE', self::getInstance());
                }
            }

            foreach ($configStream->{'message-resources'} as $message_resource) {
                $attr = $message_resource->attributes();
                ActionResourceBundle::initialize((string) $attr->parameter);
            }

            foreach ($configStream->{'propel-class'} as $propel_class) {
                $attr = $propel_class->attributes();
                self::addParam('__PROPEL_CLASS_FILE', (string) $attr->file);
            }
        } catch (\Exception $e) {
            throw ($e);
        }
    }

    /**
     * Executa uma ação do aplicativo, associado a uma variável GET (geralmente é 'do').
     *
     * @access public
     * @return void
     */
    public static function execute() {
        try {
            return Controller\ActionController::execute();
        } catch (\Exception $e) {
            throw($e);
        }
    }

}

?>